package com.tongsys.server.config.security.filter;

import com.mysql.jdbc.log.Log;
import com.tongsys.server.config.redis.RedisService;
import com.tongsys.server.config.redis.RedisUtils;
import com.tongsys.server.config.security.exception.exp;
import com.tongsys.server.entity.User;
import com.tongsys.server.utils.JwtUtils;
import com.tongsys.server.utils.WebUtils;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Objects;

@Data
@Component
public class JWTTokenFilter extends OncePerRequestFilter {

    @ApiModelProperty("登录请求地址")
    @Value("${request.login.url}")
    private String loginUrl;



    @Autowired
    private RedisUtils redisUtils;
    @Autowired
    private RedisService redisService;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        //不是登录请求
        try {
            String url = request.getRequestURI();
            //是登录，直接放行
            if(loginUrl.equals(url)){
                filterChain.doFilter(request,response);
                //结束
                return;
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        //不是登录请求，需要验证

        //获取 token
        String token=request.getHeader("token");
        //头部中没token 就从参数中获取
        if (ObjectUtils.isEmpty(token)){
            //获取请求中的token
            token=request.getParameter("token");
        }
        //如果还是不存在
        if (ObjectUtils.isEmpty(token)){
            //抛出异常
            throw new exp("请登录");
        }

        //解析 token ,获取用户ID
        Integer userId = JwtUtils.getUserId(token);
        //获取redis中的用户信息
        User obj = (User)redisUtils.getCacheObject("login:" + userId);

        if (Objects.isNull(obj)){
            //不存在信息
            throw new exp("token失效，请重新登录");
        }

        // TODO 创建用户身份验证对象  获取权限信息 封装到Authentication 对象中,参数数封装了的对象和权限
        UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(obj,null,obj.getAuthorities()); //这点必须选择三个参数的对象
        //设置请求信息
        usernamePasswordAuthenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
        //将认证信息放入 spring security 上下文中
        SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
        //验证通过，放行
        filterChain.doFilter(request,response);
    }

}
